/*
 * $Id: stdlib.h,v 1.31 2006-03-31 17:14:06 bacon Exp $
 */

#ifndef _XP_BAS_STDLIB_H_
#define _XP_BAS_STDLIB_H_

#include <xp/types.h>
#include <xp/macros.h>

#include <stdlib.h>

#define XP_EXIT_SUCCESS EXIT_SUCCESS
#define XP_EXIT_FAILURE EXIT_FAILURE

/* definition for rc4 functions */
#define XP_RC4_MAX_PASSWD 256
struct xp_rc4_t
{
	xp_byte_t passwd[XP_RC4_MAX_PASSWD];
	xp_size_t passwd_len;

	int sbox[256];
	int key[256];
	int idxa;
	int idxb;

	xp_bool_t __dynamic;
};
typedef struct xp_rc4_t xp_rc4_t;

/* definition for md5 functions */
struct xp_md5_t
{
	xp_uint32_t count[2];
	xp_uint32_t state[4];
	xp_byte_t   buffer[64];
	xp_bool_t   __dynamic;
};
typedef struct xp_md5_t xp_md5_t;

#ifdef __cplusplus
extern "C" {
#endif

#define xp_exit exit 
#define xp_abort abort 

/* 
 * FUNCTION: xp_bitcount 
 */
int xp_bitcount (void* num, xp_size_t size);

int xp_digtoi (xp_char_t c, int base);
xp_size_t xp_bytetostr_upper (xp_byte_t byte, 
	xp_char_t* buf, xp_size_t size, int base, xp_char_t fill);
xp_size_t xp_bytetostr_lower (xp_byte_t byte,
	xp_char_t* buf, xp_size_t size, int base, xp_char_t fill);

int xp_atoi (const xp_char_t* str);
long xp_atol (const xp_char_t* str);

xp_int_t xp_strtoint (const xp_char_t* str);
xp_long_t xp_strtolong (const xp_char_t* str);
xp_uint_t xp_strtouint (const xp_char_t* str);
xp_ulong_t xp_strtoulong (const xp_char_t* str);
xp_real_t xp_strtoreal (const xp_char_t* str);

/* rc4 functions */
xp_rc4_t* xp_rc4_open (xp_rc4_t* rc4);
void xp_rc4_close (xp_rc4_t* rc4);
void xp_rc4_set_passwd (xp_rc4_t* rc4, const void* pw, xp_size_t psz);
void xp_rc4_restart (xp_rc4_t* rc4);
xp_byte_t xp_rc4_cipher (xp_rc4_t* rc4, xp_byte_t c);

/* stand-alone rc4 function */
xp_size_t xp_cipherrc4 (
	const void* src, xp_size_t ssz,
	void* dst, xp_size_t dsz, 
	const void* pw, xp_size_t pwlen);

/* base-64 functions */
xp_size_t xp_encodebase64 (
	const xp_byte_t* in, xp_size_t isz, 
	xp_byte_t* out, xp_size_t osz, xp_size_t* xsz);
xp_size_t xp_decodebase64 (
	const xp_byte_t* in, xp_size_t isz,
	xp_byte_t* out, xp_size_t osz, xp_size_t* xsz);

/* md5 functions */
xp_md5_t* xp_md5_open (xp_md5_t* md5);
void xp_md5_close (xp_md5_t* md5);
void xp_md5_update (xp_md5_t* md5, const void* data, xp_uint32_t len);
xp_size_t xp_md5_digest (xp_md5_t* md5, xp_byte_t* digest, xp_size_t size);

#ifdef __cplusplus
}
#endif

/* xp_strtoi (const xp_char_t* nptr, xp_char_t** endptr, int base) */
#define XP_STRTOI(value,nptr,endptr,base) \
	{ \
		int __strtoi_f = 0, __strtoi_v; \
		const xp_char_t* __strtoi_ptr = nptr; \
		for (;;) { \
			xp_char_t __strtoi_c = *__strtoi_ptr; \
			if (__strtoi_c == XP_CHAR(' ') || \
			    __strtoi_c == XP_CHAR('\t')) { __strtoi_ptr++; continue; } \
			if (__strtoi_c == XP_CHAR('-')) { __strtoi_f++; __strtoi_ptr++; } \
			if (__strtoi_c == XP_CHAR('+')) { __strtoi_ptr++; } \
			break; \
		} \
		for (value = 0; (__strtoi_v = xp_digtoi(*__strtoi_ptr, base)) < base; __strtoi_ptr++) { \
			value = value * base + __strtoi_v; \
		} \
		if (endptr != XP_NULL) *((const xp_char_t**)endptr) = __strtoi_ptr; \
		if (__strtoi_f > 0) value *= -1; \
	}

/* xp_strxtoi (const xp_char_t* nptr, xp_size_t len, xp_char_char** endptr, int base) */
#define XP_STRXTOI(value,nptr,len,endptr,base) \
	{ \
		int __strtoi_f = 0, __strtoi_v; \
		const xp_char_t* __strtoi_ptr = nptr; \
		const xp_char_t* __strtoi_end = __strtoi_ptr + len; \
		value = 0; \
		while (__strtoi_ptr < __strtoi_end) { \
			xp_char_t __strtoi_c = *__strtoi_ptr; \
			if (__strtoi_c == XP_CHAR(' ') || __strtoi_c == XP_CHAR('\t')) { \
				__strtoi_ptr++; continue; \
			} \
			if (__strtoi_c == XP_CHAR('-')) { __strtoi_f++; __strtoi_ptr++; } \
			if (__strtoi_c == XP_CHAR('+')) { __strtoi_ptr++; } \
			break; \
		} \
		for (value = 0; __strtoi_ptr < __strtoi_end && \
		                (__strtoi_v = xp_digtoi(*__strtoi_ptr, base)) != base; __strtoi_ptr++) { \
			value = value * base + __strtoi_v; \
		} \
		if (endptr != XP_NULL) *((const xp_char_t**)endptr) = __strtoi_ptr; \
		if (__strtoi_f > 0) value *= -1; \
	}

#endif
